package com.lijinquan.springcloud.controller;

import cn.lijinquan.p2p.entites.Creditor;
import cn.lijinquan.p2p.entites.FundingNotMatched;
import cn.lijinquan.p2p.entites.WaitMatchMoney;
import com.lijinquan.springcloud.service.CreditorService;
import com.lijinquan.springcloud.service.FundingNotMatchedService;
import com.lijinquan.springcloud.service.WaitMoneyService;
import com.lijinquan.springcloud.utils.ClaimsType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by lijinquan on 2019/10/12.
 */
@RestController
public class WaitMoneyController {

    @Autowired
    private WaitMoneyService waitMoneyService;
    @Autowired
    private FundingNotMatchedService fundingNotMatchedService;

    @Autowired
    private CreditorService creditorService;

    @RequestMapping("/accountLog/selectWaitMoney")
    public Map<String, Object> selectWaitMoney() {
        // 3.1 查询所有待匹配资金队列
        List<WaitMatchMoney> waitMatchMoneys = waitMoneyService.selectWaitMatch();
        // 3.2查询待匹配资金队列统计信息
        WaitMatchMoney waitMatchMoneyCount = waitMoneyService.selectWaitMatchCount();
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("listMatch", waitMatchMoneys);
        returnMap.put("waitMatchCount", waitMatchMoneyCount);

        return returnMap;
    }

    @RequestMapping("/match/startMatchByManually")
    public Boolean startMatchByManually() {
        Boolean result = false;

        // 1.得到所有的待匹配资金信息
        FundingNotMatched fCondition=new FundingNotMatched();
        fCondition.setfIsLocked(10901);
        List<FundingNotMatched> invest = fundingNotMatchedService.findByCondition(fCondition);// 得到10901
        // 2.得到所有的待匹配的债权信息
        Map<String,Object> cM=new HashMap<>();
        cM.put("debtStatus",ClaimsType.CHECKED);
        List<Integer> matchedStatus =new ArrayList<>();
        matchedStatus.add(ClaimsType.PART_MATCH);
        matchedStatus.add(ClaimsType.UNMATCH);
        cM.put("matchedStatus",matchedStatus);
        List<Creditor> creditors = creditorService.getCreditorListByCondition(cM);// 只能得到11302
        // 3.执行匹配操作
        match(invest, creditors);
        return result;
    }

    @Transactional
    private void match(List<FundingNotMatched> invest, List<Creditor> creditors) {

        // 1.得到所有的待匹配资金金额
        BigDecimal investMoney = getInvestMoney(invest);
        // 2.得到所有的待匹配的债权的金额
        BigDecimal creditorMoney = getCreditorMoney(creditors);

        // 3.根据金额来判断如何匹配
        BigDecimal sub = investMoney.subtract(creditorMoney);
        if (sub.intValue() > 0) { // 资金大于债权
            // 4.创建两个队列
            LinkedList<FundingNotMatched> fmms = new LinkedList<>(invest);// 资金队列
            LinkedList<Creditor> cms = new LinkedList<>(creditors);// 债权队列

            if(cms.size()>0){// 判断债权队列不为空
                // 处理匹配操作
            }

        } else if (sub.intValue() < 0) { // 债权大于资金
            LinkedList<FundingNotMatched> fmms = new LinkedList<>(invest);// 资金队列
            LinkedList<Creditor> cms = new LinkedList<Creditor>(creditors);// 债权队列
            while (!fmms.isEmpty()) { // 判断资金队列不为空
                // 5 处理匹配操作
                // 5.1 得到资金队列中每一个元素的的可用待匹配资金
                FundingNotMatched fnm = fmms.poll(); // 相当于removeFirst
                // 5.2得到债权队列中可用匹配金额
                Creditor cm = cms.poll();
                // 5.3债权队列最后是不为空的，而资金队列最后是为空
                BigDecimal big = BigDecimal.valueOf(fnm.getfNotMatchedMoney().doubleValue())
                        .subtract(BigDecimal.valueOf(cm.getAvailableMoney()));
                if (big.intValue() > 0) { // 资金大于债权
                    fnm.setfNotMatchedMoney(big.abs().doubleValue());
                    fmms.push(fnm);// 将剩余的资金重新压入

                } else if (big.intValue() < 0) {// 债权大于资金
                    cm.setAvailableMoney(big.abs().doubleValue());
                    cms.push(cm);// 将剩余的债权重新压入
                }

            }
            // 6.将所有的资金列表中的元素信息改变
            // 修改 fIsLocked=10902 fNotMatchedMoney=0 条件是 fIsLocked=10901
            updateInvest(invest);
            // 7.处理债权中的元素的信息 1.有些完全匹配 2.在cms中有些债权是部分匹配的，有些是没有匹配
            // 7.1 处理债权队列中的元素 availableMoney要判断是否改变了 来确定是没有匹配，还是部分匹配
            updateCreditorQueue(cms);
            creditors.removeAll(cms);
            // 7.2怎样得到已经匹配的债权creditors-cms creditors.removeAll(cms);
            // 注意：必须重写Creditor中的equals与hashCode方法只比主键
            updateCreditor(creditors);

        } else {

        }
    }


    /**
     * 处理所有匹配的债权
     * @param creditors
     */
    private void updateCreditor(List<Creditor> creditors) {
        for (Creditor cm : creditors) {
            Creditor _cm = creditorService.getCreditorById(cm.getId());
            _cm.setAvailableMoney(0);
            _cm.setMatchedMoney(cm.getAvailableMoney());
            _cm.setMatchedStatus(11402); // 完全匹配
            creditorService.modifyCreditor(_cm);
        }
    }


    /**
     * 将债权队列中的数据进行操作
     * @param cms
     */
    private void updateCreditorQueue(LinkedList<Creditor> cms) {
        // 原因:我们想要从数据库中查询数据，不是从缓存中获取
        for (Creditor cm : cms) {

            Creditor _cm= creditorService.getCreditorById(cm.getId());

            if (BigDecimal.valueOf(_cm.getAvailableMoney()).equals(BigDecimal.valueOf(cm.getAvailableMoney()))) {
                // 说明没有匹配

            } else {
                // 部分匹配
                _cm.setMatchedMoney(_cm.getAvailableMoney() - cm.getAvailableMoney()); // 设置匹配的金额
                _cm.setAvailableMoney(cm.getAvailableMoney());// 设置可用余额
                _cm.setMatchedStatus(11401);// 部分匹配
                creditorService.modifyCreditor(_cm);
            }
        }

    }


    /**
     * 修改所有的待匹配资金信息
     * @param invest
     */
    private void updateInvest(List<FundingNotMatched> invest) {
        for (FundingNotMatched fm : invest) {
            FundingNotMatched _fm = fundingNotMatchedService.getFundingNotMatchedById(fm.getfId()); // 根据id查询
            // 改变
            _fm.setfNotMatchedMoney(0.0);// 将待匹配资金改变为0
            _fm.setfIsLocked(10902);// 将待匹配修改为确认匹配
            fundingNotMatchedService.modifyFundingNotMatched(_fm);
        }
    }

    // 获取所有待匹配债权金额
    private BigDecimal getCreditorMoney(List<Creditor> creditors) {
        BigDecimal bg = new BigDecimal(0);
        for (Creditor cm : creditors) {
            bg = bg.add(BigDecimal.valueOf(cm.getAvailableMoney()));// 将所有可用金额累加
        }
        return bg;
    }


    /**
     * 获取所有待匹配的资金金额
     * @param invest
     * @return
     */
    private BigDecimal getInvestMoney(List<FundingNotMatched> invest) {
        BigDecimal bg = new BigDecimal(0);
        for (FundingNotMatched cm : invest) {
            bg = bg.add(BigDecimal.valueOf(cm.getfNotMatchedMoney()));// 将所有可用待匹配金额累加
        }
        return bg;
    }


}
